<template>
  <van-form>
    <!-- <van-button
      type="primary"
      @click="elementFind"
    >
      表单元素check
    </van-button> -->
    <!-- <van-button
      type="info"
      @click="verification"
    >
      表单验证
    </van-button> -->
    <!-- <van-button
      type="danger"
      @click="collectInfo"
    >
      信息收集
    </van-button> -->
    <!-- {{ formComponent.length }} -->
    <section
      v-for="({ component, prop }, index) in formComponent"
      :key="index"
      class="component"
    >
      <!-- {{ index + 1 }} -->
      <component
        :is="component"
        ref="fieldComp"
        v-model="prop.value"
        v-bind="prop"
        @action="triggerEvent('action')"
      />
    </section>
  </van-form>
</template>

<script>
import _ from 'lodash';
import generatorForm from '@/components/Form/mixins/generator';

export default {
  name: 'VanFormGenerator',

  mixins: [generatorForm],

  data() {
    return {
      // 表单
      formComponent: []
    };
  },

  computed: {
    fieldComp() {
      return this.$refs.fieldComp;
    },

    // 元素查找
    components() {
      let elements = [];
      _.forEach(this.fieldComp, (o) => {
        elements.push(o.getElements());
      });
      elements = _.flattenDeep(elements);
      return elements;
    },

    // 信息收集
    collectInfo() {
      const collectMap = [];
      this.$_.forEach(this.fieldComp, ({ collectInfo = {} }) => {
        collectMap.push(collectInfo);
      });
      this.triggerEvent('collectInfo');

      // 一维数组
      const temp = this.$_
        .flattenDeep(collectMap);

      return this.$_
        .filter(temp, (o) => (o !== null));
    }
  },

  watch: {
    'formGenerator.generator': {
      handler() {
        this.formComponent = [];
        this.$nextTick(() => {
          this.generator();
        });
      },
      immediate: true
    }
  },

  methods: {
    // 获取元素属性
    getElementAttribute(attr) {
      return this.$_.map(this.fieldComp, (o) => o[attr] && o[attr]);
    },

    // 表单验证
    validate() {
      // test
      // 1、获取组件实例
      // 2、validate 执行
      // 3、promise.error 马上停止执行

      const elements = this.getElements();
      const validateMap = [];

      // 数组拍平
      // function deepValidate(fieldComp) {
      //   _.forEach(fieldComp, (o) => {
      //     const val = o();
      //     if (val.constructor === Array) {
      //       deepValidate(val);
      //     } else {
      //       validateMap.push(val);
      //     }
      //   });
      // }
      // deepValidate(this.getElementAttribute('validate'));
      _.forEach(elements, ({ validate }) => {
        if (validate) {
          validateMap.push(validate());
        }
      });
      // elementFind

      return new Promise((resolve, reject) => {
        Promise.all(validateMap)
          .then((data) => resolve(data))
          .catch((err) => reject(err))
          .finally(() => this.triggerEvent('validate'));
      });
    },

    // 表单校验
    verification() {
      this.validate();
    },

    // elements
    getElements() {
      const { fieldComp } = this.$refs;
      let elements = [];
      _.forEach(fieldComp, (o) => {
        elements.push(o.getElements());
      });
      elements = _.flattenDeep(elements);
      return elements;
    },

    // 表单生成
    generator() {
      this.$emit('beforeGenerator');

      const { generator } = this.formGenerator;

      this.generatorComp(generator);

      this.$nextTick(() => {
        this.triggerEvent('generator');
      });
    },

    // 事件触发
    triggerEvent(evt, val) {
      this.$emit(evt, val);

      setTimeout(() => {
        this.$emit('action');
      }, 500);
    }
  }
};
</script>
